package api

import (
	"OJCenter/global"
	"OJCenter/idl"
	"OJCenter/tool"
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"math/rand"
	"net/http"
	"strconv"
	"time"
)

type auth struct {
	Uid      string `validate:"len=10,required"`
	Password string `valid:"Required;"`
}

// @Summary	获取权限
// @Produce	json
// @Param		uid			formData	string			true	"用户ID"
// @Param		password	formData	string			true	"密码"
// @Success	200			{object}	global.Response	"token"
// @Fail		400  {object} global.Response "token"
// @Router		/api/v1/auth [post]
func (a *Api) GetAuth(c *gin.Context) {

	uid := c.PostForm("uid")
	password := c.PostForm("password")

	au := auth{Uid: uid, Password: password}
	validate := validator.New()

	err := validate.Struct(&au)
	if err != nil {
		global.MarkErrors(err.(validator.ValidationErrors))
		global.Res(c, http.StatusBadRequest, global.INVALID_PARAMS, nil)
		return
	}

	_uid, err := strconv.Atoi(uid)
	if err != nil {
		return
	}
	info, err := a.M.CheckAuth(int64(_uid), password)

	if err != nil {
		return
	}

	if err != nil {
		global.Res(c, http.StatusInternalServerError, global.ERROR_AUTH_CHECK_TOKEN_FAIL, nil)
		return
	}

	if info == nil {
		global.Res(c, http.StatusUnauthorized, global.ERROR_AUTH, nil)
		return
	}

	token, err := tool.GenerateToken(uid, (*info)["admin_type"])
	if err != nil {
		global.Res(c, http.StatusInternalServerError, global.ERROR_AUTH_TOKEN, nil)
		return
	}

	global.Res(c, http.StatusOK, global.SUCCESS, map[string]string{
		"token": token,
	})
}

//	@Summary	创建用户
//	@Produce	json
//
// Param  token header  string true  "JWT"
//
//	@Param		body	body		idl.User		true	"用户信息//可以少一些字段，具体看数据库"
//	@Success	200		{object}	global.Response	""
//	@Fail		400  {object} global.Response ""
//	@Router		/api/v1/createAuthority [post]
func (a *Api) CreateAuthority(c *gin.Context) {
	var user idl.User

	err := c.ShouldBindJSON(&user)
	if err != nil {
		global.Res(c, http.StatusBadRequest, global.INVALID_PARAMS, err)
	}

	validate := validator.New()
	err = validate.Struct(&user)
	if err != nil {
		global.MarkErrors(err.(validator.ValidationErrors))
		global.Res(c, http.StatusBadRequest, global.INVALID_PARAMS, nil)
		return
	}

	err = a.M.CreateUser(&user)
	if err != nil {
		global.Res(c, http.StatusBadRequest, global.INVALID_PARAMS, err)
	}

	global.Res(c, http.StatusOK, global.SUCCESS, new(interface{}))
}

// @Summary	删除用户
// @Produce	json
// @Param		body	body		[]int			true	"用户ID"
// @Success	200		{object}	global.Response	""
// @Fail		400  {object} global.Response ""
// @Router		/api/v1/deleteAuthority [post]
func (a *Api) DeleteAuthority(c *gin.Context) {
	var uids []int64

	err := c.ShouldBindJSON(&uids)
	if err != nil {
		global.Res(c, http.StatusBadRequest, global.INVALID_PARAMS, err)
	}

	sum, fu := a.M.DeleteUsers(&uids)
	if sum != len(uids) {
		global.Res(c, http.StatusBadRequest, global.INVALID_PARAMS, fu)
	}

	global.Res(c, http.StatusOK, global.SUCCESS, new(interface{}))
}

// @Summary	更新用户
// @Produce	json
// @Param		body	body		[]idl.User		true	"用户信息"
// @Success	200		{object}	global.Response	""
// @Fail		400  {object} global.Response{Data=[]idl.User} ""
// @Router		/api/v1/updateAuthority [post]
func (a *Api) UpdateAuthority(c *gin.Context) {
	var users []idl.User

	err := c.ShouldBindJSON(&users)
	if err != nil {
		global.Res(c, http.StatusBadRequest, global.INVALID_PARAMS, err)
	}

	validate := validator.New()
	for _, t := range users {
		err := validate.Struct(&t)
		if err != nil {
			global.MarkErrors(err.(validator.ValidationErrors))
			global.Res(c, http.StatusBadRequest, global.INVALID_PARAMS, nil)
			return
		}
	}

	sum, fu := a.M.UpdateUsers(&users)
	if sum != len(users) {
		global.Res(c, http.StatusRequestedRangeNotSatisfiable, global.INVALID_PARAMS, fu)
	}
	global.Res(c, http.StatusOK, global.SUCCESS, new(interface{}))

}

// @Summary	发送邮件
// @Produce	json
// @Param		uid	query		string			true	"用户ID"
// @Success	200	{object}	global.Response	""
// @Fail		400  {object} global.Response ""
// @Router		/api/v1/mailAuthority [post]
func (a *Api) MailAuthority(c *gin.Context) {
	var code uint32
	_uid := c.Query("uid")
	uid, _ := strconv.Atoi(_uid)
	rnt := rand.New(rand.NewSource(time.Now().Unix()))
	code = uint32(rnt.Int31n(1000000))
	err := a.M.SetVerifyCode(int64(uid), code)
	if err != nil {
		global.Logger.Errorf("set mail code failed,err:%v", err)
	}
	if err != nil {
		global.Res(c, http.StatusBadRequest, global.INVALID_PARAMS, err)
		return
	}

	if err != nil {
		global.Res(c, http.StatusBadRequest, global.INVALID_PARAMS, err)
		return
	}
	global.Res(c, http.StatusOK, global.SUCCESS, new(interface{}))

}

// @Summary	获取用户列表
// @Produce	json
// @Param		page	query		int								true	"页码"
// @Param		limit	query		int								true	"限制"
// @Success	200		{object}	global.Response{Data=idl.User}	""
// @Fail		400  {object} global.Response ""
// @Router		/api/v1/getAuthorityList [Get]
func (a *Api) GetAuthorityList(c *gin.Context) {

	limit, _ := strconv.Atoi(c.Query("limit"))
	page, _ := strconv.Atoi(c.Query("page"))

	sum, err := a.M.GetUserList(page, limit)
	if err != nil && sum == nil {
		global.Res(c, http.StatusBadRequest, global.INVALID_PARAMS, err)
		return
	}
	global.Res(c, http.StatusOK, global.SUCCESS, sum)
}

func (a *Api) SelectAuthority(c *gin.Context) {
	var user idl.User

	err := c.ShouldBindJSON(&user)
	if err != nil {
		global.Res(c, http.StatusBadRequest, global.INVALID_PARAMS, err)
		return
	}
	validate := validator.New()
	err = validate.Struct(&user)
	if err != nil {
		global.MarkErrors(err.(validator.ValidationErrors))
		global.Res(c, http.StatusBadRequest, global.INVALID_PARAMS, nil)
		return
	}
	fu, err := a.M.SelectUsers(user)
	if err != nil && fu == nil {
		global.Res(c, http.StatusBadRequest, global.INVALID_PARAMS, err)
		return
	}
	global.Res(c, http.StatusOK, global.SUCCESS, new(interface{}))
}

// @Summary	获取用户列表
// @Produce	json
// @Param		uid			query		int				true	"uid"
// @Param		verifyCode	query		int				true	"验证码"
// @Success	200			{object}	global.Response	""
// @Fail		400  {object} global.Response ""
// @Router		/api/v1/verifyMailAuthority [Get]
func (a *Api) VerifyMailAuthority(c *gin.Context) {
	_uid := c.Query("uid")
	uid, _ := strconv.Atoi(_uid)
	_code := c.Query("verifyCode")
	code, _ := strconv.Atoi(_code)
	mailCode, err := a.M.GetVerifyCode(int64(uid))
	if err != nil {
		global.Res(c, http.StatusBadRequest, global.INVALID_PARAMS, err)
	}
	if uint32(code) != mailCode {
		global.Res(c, http.StatusBadRequest, global.INVALID_PARAMS, err)
		return
	}
	global.Res(c, http.StatusOK, global.SUCCESS, new(interface{}))

}
